package cn.ddiancan.xddcloud.common.config;

import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import cn.ddiancan.xddcloud.common.interceptor.HeaderInterceptor;
import cn.ddiancan.xddcloud.common.interceptor.InComingRequestInterceptor;
import cn.ddiancan.xddcloud.common.interceptor.JWTInterceptor;
import cn.ddiancan.xddcloud.common.interceptor.OutgoingRequestInterceptor;
import cn.ddiancan.xddcloud.common.loadbalancer.XddclouedLoadbalancerConfigruation;
import cn.ddiancan.xddcloud.common.security.JwtService;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

@Configuration
@ComponentScan("cn.ddiancan.xddcloud.common")
@LoadBalancerClients(defaultConfiguration = XddclouedLoadbalancerConfigruation.class)
public class XddcloudCommonConfiguration {

    private static final Logger logger = LoggerFactory.getLogger(XddcloudCommonConfiguration.class);

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(JwtService jwtService) {
        RestTemplate restTemplate = new RestTemplate();
        HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory =
            new HttpComponentsClientHttpRequestFactory();
        try {
            SSLConnectionSocketFactory sslSocketFactory =
                SSLConnectionSocketFactoryBuilder.create().setSslContext(createIgnoreVerifySSL()).build();
            HttpClientConnectionManager cm =
                PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
            CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
            httpComponentsClientHttpRequestFactory.setHttpClient(httpClient);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        List<HttpMessageConverter<?>> httpMessageConverters = restTemplate.getMessageConverters();
        httpMessageConverters.forEach(httpMessageConverter -> {
            if (httpMessageConverter instanceof StringHttpMessageConverter) {
                StringHttpMessageConverter messageConverter = (StringHttpMessageConverter) httpMessageConverter;
                messageConverter.setDefaultCharset(StandardCharsets.UTF_8);
            }
        });
        // 调整了这里
        httpComponentsClientHttpRequestFactory.setConnectTimeout(50000);
        restTemplate.setRequestFactory(httpComponentsClientHttpRequestFactory);
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        restTemplate.setInterceptors(interceptors(jwtService));
        return restTemplate;
    }

    private List<ClientHttpRequestInterceptor> interceptors(JwtService jwtService) {
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
        interceptors.add(new HeaderInterceptor());
        interceptors.add(new JWTInterceptor(jwtService));
        interceptors.add(new InComingRequestInterceptor());
        interceptors.add(new OutgoingRequestInterceptor());
        return interceptors;
    }

    private static SSLContext createIgnoreVerifySSL() {
        try {
            SSLContext sc = SSLContext.getInstance("TLS");

            // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
            X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            sc.init(null, new TrustManager[]{trustManager}, null);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
        return null;
    }
}
